﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using HalconDotNet;
using System.Runtime.InteropServices;
using System.Windows.Media.Imaging;
using MathWorks.MATLAB.NET.Arrays;
using System.Windows.Media;
using System.IO;
using System.IO.Compression;

namespace YsHObject2Bitmap
{
    /// <summary>
    /// Halcon  HObject 对象转化为 C# Bitmap
    /// </summary>
    public class HObject2Bitmap
    {
        //像素格式
        System.Windows.Media.PixelFormat pixelFormat = System.Windows.Media.PixelFormats.Indexed8;
        //256调色板
        List<System.Windows.Media.Color> colors256 = new List<System.Windows.Media.Color>();

        //MATLAB RGB
        BGR2Byte.GetBytes bgr = null;

        public HObject2Bitmap()
        {
            //调色板
            for (int i = 0; i <= 255; i++)
            {
                colors256.Add(System.Windows.Media.Color.FromRgb((byte)i, (byte)i, (byte)i));
            }

            bgr = new BGR2Byte.GetBytes();
        }

        /// <summary>
        /// 获取
        /// </summary>
        /// <param name="hoImage"></param>
        /// <returns></returns>
        public BitmapSource GetBitmapSource(HalconDotNet.HObject hoImage)
        {
          
            if (hoImage == null)
                return null;
            //计算通道
            HTuple channels;
            try
            {

                HOperatorSet.CountChannels(hoImage, out channels);
            }
            catch (Exception ex)
            {
                System.Console.WriteLine(ex.Message);

                return null;
            }
            BitmapSource res = null;
            
            if (channels == 1)
            {
                //单通道
                GenertateGrayBitmapSource(hoImage, out res);
            }
            else
            {
                //3通道
                GenertateRGBBitmapSource(hoImage, out res);
            }
            return res;
        }
       

       /// <summary>
        /// 获取 JpegBuffer
       /// </summary>
       /// <param name="hoImage"></param>
        /// <param name="qualityLevel">值的范围从 1（最低质量）到 100（最高质量），包括 1 和 100</param>
       /// <returns></returns>
        public byte[] GetJpegBuffer(HalconDotNet.HObject hoImage, int qualityLevel)
        {
            if (hoImage == null)
            {
                return null;
            }
           
            BitmapSource temp = GetBitmapSource(hoImage);
            if (temp == null)
            {
                return null;
            }

            return GetByteJpeg(temp, qualityLevel);
        }


        #region  BitmapSource
        /// <summary>
        /// 灰度图像
        /// </summary>
        /// <param name="image"></param>
        /// <param name="bitmapSource"></param>
        private void GenertateGrayBitmapSource(HObject image, out BitmapSource bitmapSource)
        {
            bitmapSource = null;
         
            try
            {
                HTuple hpoint, type, width, height;
              
                int[] ptr = new int[2];
                HOperatorSet.GetImagePointer1(image, out hpoint, out type, out width, out height);
                BitmapPalette bitmapPalette = new BitmapPalette(colors256);

                //4的倍数，不足补齐    
                int rawStride = ((int)Math.Ceiling((double)width / 4)) * 4;
                byte[] rawImage = new byte[rawStride * height];
                if (rawStride == width)
                {
                    //拷贝到 图像数组中
                    System.Runtime.InteropServices.Marshal.Copy(new IntPtr(hpoint.L), rawImage, 0, rawImage.Length);
                }
                else
                {
                    //按行拷贝
                    for (int i = 0; i < height; ++i)
                    {
                        Marshal.Copy(new IntPtr(hpoint.L + i * width), rawImage, i * rawStride, width);
                    }
                }
                bitmapSource = BitmapSource.Create(width, height,
                    96, 96, pixelFormat, bitmapPalette,
                    rawImage, rawStride);
            }
            catch
            {
               
            }


        }


        /// <summary>
        /// 3通道位图
        /// </summary>
        /// <param name="image"></param>
        /// <param name="bitmapSource"></param>
        private void GenertateRGBBitmapSource(HObject image, out BitmapSource bitmapSource)
        {
            bitmapSource = null;
           
            try
            {
                HTuple hred, hgreen, hblue, type, width, height;
            
                HOperatorSet.GetImagePointer3(image, out hred, out hgreen, out hblue, out type, out width, out height);

                //获取RGB 数据->
                byte[] B = new byte[width * height];
                byte[] G = new byte[width * height];
                byte[] R = new byte[width * height];

                Marshal.Copy(new IntPtr(hred.L), R, 0, R.Length);
                Marshal.Copy(new IntPtr(hgreen.L), G, 0, G.Length);
                Marshal.Copy(new IntPtr(hblue.L), B, 0, B.Length);

                MWNumericArray mwB = B;
                MWNumericArray mwG = G;
                MWNumericArray mwR = R;

                MWArray mwBGR = bgr.BGR(mwB, mwG, mwR);
                byte[] rawImage = (byte[])((MWNumericArray)mwBGR).ToVector(MWArrayComponent.Real);

                PixelFormat pf = PixelFormats.Bgr24;
                int rawStride = (width * pf.BitsPerPixel + 7) / 8;
                bitmapSource = BitmapSource.Create(width, height,
                   96, 96, pf, null,
                   rawImage, rawStride);
            }
            catch
            {
                
            }

        }
        #endregion



        #region JPG 压缩
        /// <summary>
        /// JPG 压缩
        /// </summary>
        /// <param name="bitmapSource"></param>
        /// <returns></returns>
        private byte[] GetByteJpeg(BitmapSource bitmapSource, int qualityLevel)
        {
            if (bitmapSource == null)
                return null;
            //创建Decoder
            var bitmapEncoder = new JpegBitmapEncoder();

            ////压缩质量
            bitmapEncoder.QualityLevel = qualityLevel;
            //加入第一帧
            bitmapEncoder.Frames.Add(BitmapFrame.Create(bitmapSource));
            MemoryStream ms = new MemoryStream();
            bitmapEncoder.Save(ms);
            return ms.ToArray();
        }

        /// <summary>
        /// JpegBuffer 转化为 BitmapSource
        /// </summary>
        /// <param name="jpegBuffer"></param>
        /// <returns></returns>
        private BitmapSource GetBitmapSource4JpegBuffer(byte[] jpegBuffer)
        {
            if (jpegBuffer != null || jpegBuffer.Length == 0)
                return null;
            JpegBitmapDecoder decoder = new JpegBitmapDecoder(new System.IO.MemoryStream(jpegBuffer), BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
            return decoder.Frames[0];
        }
        #endregion

    }

}
